/* @flow */
import { createAction, createActions, handleActions, type ActionType } from 'redux-actions';
import produce from 'immer';

/* ACTION TYPES */
const START_DRAGGING = 'common/drag/START_DRAGGING';
const END_DRAGGING = 'common/drag/END_DRAGGING';
const SET_DRAGGING_OVER = 'common/drag/SET_DRAGGING_OVER';
const CLEAR_DRAGGING_OVER = 'common/drag/CLEAR_DRAGGING_OVER';
const CHANGE_TREE_OPEN = 'common/tree/CHANGE_TREE_OPEN';
const CHANGE_TREE_SELECT = 'common/tree/CHANGE_TREE_SELECT';

/* ACTION PAYLOADS */

/* EXPORTING ACTION CREATORS / ACTION CREATORS TYPES */
export interface CommonActionCreators {
    startDragging(value: string): any;
    endDragging(): any;
    setDraggingOver(value: string): any;
    clearDraggingOver(): any;
    changeTreeOpen(payload: string): any;
    changeTreeSelect(payload: string): any;
}
/* ACTION CREATORS */

export const actionCreators: CommonActionCreators = {
    startDragging: createAction(START_DRAGGING, (payload: Array<string>) => payload),
    endDragging: createAction(END_DRAGGING),
    setDraggingOver: createAction(SET_DRAGGING_OVER, (payload: string) => payload),
    clearDraggingOver: createAction(CLEAR_DRAGGING_OVER),
    changeTreeOpen: createAction(CHANGE_TREE_OPEN, (payload: string) => payload),
    changeTreeSelect: createAction(CHANGE_TREE_SELECT, (payload: string) => payload)
};
/* ACTION FLOW TYPE */
type StartDraggingAction = ActionType<typeof actionCreators.startDragging>;
type EndDraggingAction = ActionType<typeof actionCreators.endDragging>;
type SetDraggingOverAction = ActionType<typeof actionCreators.setDraggingOver>;
type ClearDraggingOverAction = ActionType<typeof actionCreators.clearDraggingOver>;
type ChangeTreeOpenAction = ActionType<typeof actionCreators.changeTreeOpen>;
type ChangeTreeSelectAction = ActionType<typeof actionCreators.changeTreeSelect>;

/* State Types */

export type Common = {
    draggable: {
        draggingItems: Array<string>,
        draggingOverItem: string,
        isDragging: boolean
    },
    tree: {
        canCheckTypes: Array<string>,
        openedIds: Array<string>,
        checkIds: Array<string>
    },
    editable: {
        isEditableType: Array<string>
    }
};

const initialState: Common = {
    draggable: {
        draggingItems: [],
        draggingOverItem: '',
        isDragging: false
    },
    tree: {
        canCheckTypes: [],
        openedIds: [],
        checkIds: []
    },
    editable: {
        isEditableType: []
    }
};

export default handleActions(
    {
        [START_DRAGGING]: (state, action: StartDraggingAction) => {
            return produce(state, draft => {
                draft['tree'].draggingItems = action.payload;
                draft['tree'].isDragging = true;
            });
        },
        [END_DRAGGING]: state => {
            return produce(state, draft => {
                draft.tree.draggingItems = [];
                draft.tree.isDragging = false;
                draft.tree.draggingOverItem = '';
            });
        },
        [SET_DRAGGING_OVER]: (state, action: SetDraggingOverAction) => {
            return produce(state, draft => {
                if (!action || !draft) return;
                draft['tree'].draggingOverItem = action.payload;
            });
        },
        [CLEAR_DRAGGING_OVER]: state => {
            return produce(state, draft => {
                draft['tree'].draggingOverItem = '';
            });
        },
        [CHANGE_TREE_OPEN]: (state, action: ChangeTreeOpenAction) => {
            return produce(state, draft => {
                if (!action || !draft) return;
                const index = draft.treeOpenedIds.indexOf(action.payload);
                if (index !== -1) draft.treeOpenedIds.splice(0, 0, action.payload);
                else draft.treeOpenedIds.splice(index, 1);
            });
        },
        [CHANGE_TREE_SELECT]: (state, action: ChangeTreeSelectAction) => {
            return produce(state, draft => {
                if (!action || !draft) return;
                const index = draft.treeSelectIds.indexOf(action.payload);
                if (index !== -1) draft.treeSelectIds.splice(0, 0, action.payload);
                else draft.treeSelectIds.splice(index, 1);
            });
        }
    },
    initialState
);

// export function* RootSaga() {
//     console.log('sample Hello Sagas!');
// }
